package com.atguigu.spzx.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.model.dto.api.ApiProductSearchDTO;
import com.atguigu.spzx.model.entity.product.Category;
import com.atguigu.spzx.model.entity.product.Product;
import com.atguigu.spzx.model.entity.product.ProductDetails;
import com.atguigu.spzx.model.entity.product.ProductSku;
import com.atguigu.spzx.model.vo.api.product.ProductItemVO;
import com.atguigu.spzx.model.vo.api.product.ProductSpecVO;
import com.atguigu.spzx.product.mapper.CategoryMapper;
import com.atguigu.spzx.product.mapper.ProductDetailsMapper;
import com.atguigu.spzx.product.mapper.ProductMapper;
import com.atguigu.spzx.product.mapper.ProductSkuMapper;
import com.atguigu.spzx.product.service.ProductService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {
    @Resource
    CategoryMapper categoryMapper;
    @Resource
    ProductSkuMapper productSkuMapper;
    @Resource
    ProductDetailsMapper productDetailsMapper;
    //键值泛型为String: 存入的数据需要转为字符串，读取的数据就是字符串
//    @Resource
//    StringRedisTemplate stringRedisTemplate;
    //键值泛型为Object： 存入的数据会以序列化的形式写到redis中，读取时数据会反序列化为对象
    //写入到redis中的自定义类型的对象 需要实现序列化接口
    @Resource
    RedisTemplate redisTemplate;
    /*
        查询首页数据的业务：
            1、查询一级分类数据
            2、查询已上架的销量排名前10的sku
     */
    //Cacheable注解标注的方法：当缓存不存在时 执行业务方法将结果缓存，当缓存存在时直接返回缓存
    @Cacheable(value = "spzx:index",key = "'hotData'",
            unless = "#result.size()==0")//value+key用来拼接生成缓存的键  value写前缀，key可以写表达式
    @Override
    public Map<String, Object> getIndexData() {
//        //1、创建LambdaQueryWrapper对象：
//        LambdaQueryWrapper<Category> queryWrapper = Wrappers.lambdaQuery(Category.class);
//        //2、设置查询条件
//        queryWrapper.eq(Category::getParentId , 0)
//                .orderByAsc(Category::getOrderNum);
//        categoryMapper.selectList(queryWrapper);
        //1、读取缓存，如果没有查询数据库
//        Object data = redisTemplate.opsForValue().get("spzx:index:data");
//        if(data!=null){
//            return (Map<String, Object>) data;
//        }
        List<Category> categories = categoryMapper.selectList(Wrappers.lambdaQuery(Category.class)
                .eq(Category::getParentId, 0)
                .orderByAsc(Category::getOrderNum));

        List<ProductSku> productSkus = productSkuMapper.selectList(Wrappers.lambdaQuery(ProductSku.class)
                .eq(ProductSku::getStatus, 1)
                .orderByDesc(ProductSku::getSaleNum)
                .last("limit 10"));
        Map<String, Object> map = new HashMap<>();
        map.put("categoryList" ,categories );
        map.put("productSkuList" ,productSkus );
        //2、数据库查询到的数据 写入到缓存中
//        redisTemplate.opsForValue().set("spzx:index:data" , map, 200, TimeUnit.MINUTES);
        return map;
    }

    @Override
    public PageInfo<ProductSku> list(Integer pageNum, Integer pageSize, ApiProductSearchDTO productSearchDTO) {
        //sku数据需要多表联查，有些条件在spu表中  需要的数据在sku表中
        //使用mp自定义分页查询
        //1、创建分页对象： 用来携带分页页码和pageSize条件
        Page<ProductSku> page = new Page<>(pageNum,pageSize);
        //2、使用自定义sql查询 并传入分页对象 和条件对象(携带查询条件)
        //queryWrapper组装查询条件
        QueryWrapper queryWrapper = Wrappers.query(ProductSku.class);
        Long brandId = productSearchDTO.getBrandId();
        Long category1Id = productSearchDTO.getCategory1Id();
        Long category2Id = productSearchDTO.getCategory2Id();
        Long category3Id = productSearchDTO.getCategory3Id();
        String keyword = productSearchDTO.getKeyword();
        Integer order = productSearchDTO.getOrder();
        if(brandId!=null){
            queryWrapper.eq("t2.brand_id", brandId);
        }
        if(category1Id!=null){
            queryWrapper.eq("t2.category1_id", category1Id);
        }
        if(category2Id!=null){
            queryWrapper.eq("t2.category2_id", category2Id);
        }
        if(category3Id!=null){
            queryWrapper.eq("t2.category3_id", category3Id);
        }
        if(!StringUtils.isEmpty(keyword)){
            queryWrapper.like("t1.sku_name" , keyword);
        }
        switch (order){
            case 1:
                queryWrapper.orderByDesc("t1.sale_num");
                break;
            case 2:
                queryWrapper.orderByAsc("t1.sale_price");
                break;
            default:
                queryWrapper.orderByDesc("t1.sale_price");
        }
        List<ProductSku> productSkus = productSkuMapper.selectListByCondition2(page , queryWrapper);
        //3、封装PageInfo对象返回
        PageInfo<ProductSku> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);
        pageInfo.setTotal(page.getTotal());
        pageInfo.setList(productSkus);
        return pageInfo;
    }
    //每个商品详情应该缓存自己的数据
    @Cacheable(value = "spzx:product",key = "'item:'+#skuId")
    @Override
    public ProductItemVO getItemBySkuId(Long skuId) {
        //1、查询sku
        ProductSku productSku = productSkuMapper.selectById(skuId);
        //2、查询spu：product
        Product product = baseMapper.selectById(productSku.getProductId());
        //3、查询productDetails：详情图
        ProductDetails productDetails = productDetailsMapper.selectById(productSku.getProductId());
//        productDetails.getImageUrls()
        List<String> detailsImageUrlList = StringUtils
                .isEmpty(productDetails.getImageUrls())?
                null:Arrays.asList(productDetails.getImageUrls().split(","));
        //4、准备轮播图数据
        List<String> sliderUrlList = StringUtils
                .isEmpty(product.getSliderUrls())?
                null:Arrays.asList(product.getSliderUrls().split(","));
        //5、准备规格属性值：  spu选择的规格属性值列表会存入到product中，每个sku使用了规格属性值列表中的唯一的一套组合
        //[{"key":"颜色","valueList":["白色"]},{"key":"内存","valueList":["8G","12G"]}]
        String specValue = product.getSpecValue();
        List<ProductSpecVO>  specValueList = StringUtils.isEmpty(specValue)
                // 将json数组中每个json转为ProductSpecVO类型的对象 存入到list集合中
                ?null: JSON.parseArray(specValue,ProductSpecVO.class);
        // 绿色 + 8G + 128G + 不锈钢 ->  18 , 绿色 + 8G + 128G + 塑料1->19,  : 一个spu下所有的sku的规格属性值 id映射
        //6、查询spu下所有的sku集合
        List<ProductSku> productSkuList = productSkuMapper.selectList(Wrappers.lambdaQuery(ProductSku.class)
                .eq(ProductSku::getProductId, productSku.getProductId())
                .eq(ProductSku::getStatus, 1));

        Map<String, Long> map = productSkuList.stream()
//                .filter(sku-> !StringUtils.isEmpty(sku.getSkuSpec()))
                //将集合中每个对象的SkuSpec属性当做键，Id当做值 存入到map中
                .collect(Collectors.toMap(ProductSku::getSkuSpec, ProductSku::getId));

        ProductItemVO productItemVO = new ProductItemVO();
        productItemVO.setProduct(product);
        productItemVO.setProductSku(productSku);
        productItemVO.setDetailsImageUrlList(detailsImageUrlList);
        productItemVO.setSliderUrlList(sliderUrlList);
        productItemVO.setSpecValueList(specValueList);
        productItemVO.setSkuSpecValueMap(map);
        return productItemVO;
    }

//    @Override
//    public PageInfo<ProductSku> list(Integer pageNum, Integer pageSize, ApiProductSearchDTO productSearchDTO) {
//        //sku数据需要多表联查，有些条件在spu表中  需要的数据在sku表中
//        //使用mp自定义分页查询
//        //1、创建分页对象： 用来携带分页页码和pageSize条件
//        Page<ProductSku> page = new Page<>(pageNum,pageSize);
//        //2、使用自定义sql查询 并传入分页对象 和条件对象(携带查询条件)
//        List<ProductSku> productSkus = productSkuMapper.selectListByCondition(page , productSearchDTO);
//        //3、封装PageInfo对象返回
//        PageInfo<ProductSku> pageInfo = new PageInfo<>();
//        pageInfo.setPageNum(pageNum);
//        pageInfo.setPageSize(pageSize);
//        pageInfo.setTotal(page.getTotal());
//        pageInfo.setList(productSkus);
//        return pageInfo;
//    }
}
